package ALBasicServer.ALProcess;

import java.util.ArrayList;
import java.util.List;

import ALBasicServer.ALProcess.SynTask.ALProcessStepActionMonoTask;
import ALBasicServer.ALProcess.SynTask.ALProcessStepFuncMonoTask;
import ALBasicServer.ALProcess.SynTask._AALProcessBasicMonoTask;
import ALBasicServer.ALServerSynTask.ALSynTaskManager;
import ALServerLog.ALServerLog;

/************************
 * 多个步骤同时执行的执行对象
 * 
 * ALMultiProcess 会将带入的每一个处理都用一个task执行。每个task执行的时候会带入一个action回调。执行完成要调用action才可以继续流程。 当所有步骤都执行完毕才会进入下一个环节
 * @author mj
 *
 */
public class ALMultiProcess extends _AALProcess implements _IALProcessAction
{
    /// <summary>
    /// 创建一个多过程过程对象
    /// </summary>
    /// <returns></returns>
    public static ALMultiProcess CreateMultiProcess(String _processTag) { return new ALMultiProcess(_processTag); }

    /// <summary>
    /// 执行的任务队列
    /// </summary>
    private List<_AALProcessBasicMonoTask> _m_lDealTaskList;
    //步骤统计对象
    private ALStepCounter _m_scStepCounter;

    protected ALMultiProcess(String _processTag)
    {
    	super(_processTag);
    	
        _m_lDealTaskList = new ArrayList<_AALProcessBasicMonoTask>();
        
        _m_scStepCounter = new ALStepCounter();
    }
    
	/**************
	 * 单纯的一个纯函数处理
	 * 
	 * 这里直接处理完成
	 * @param _process
	 */
    @Override
	public void dealAction()
	{
    	_onProcessDone();
	}

    /// <summary>
    /// 添加一个执行过程
    /// </summary>
    /// <param name="_process"></param>
    /// <returns></returns>
    public ALMultiProcess addProcess(_AALProcess _process)
    {
        if(null == _process)
            return this;

        if(isRunning())
        {
            ALServerLog.Error("add process when process started!");
            return this;
        }

        synchronized (_m_lDealTaskList) {
	        //加入队列返回
	        _m_lDealTaskList.add(_process);
        }
        //设置父节点
        _process.setParentProcess(this);

        return this;
    }

    /// <summary>
    /// 增加一个过程处理，如果处理过程出现异常则调用失败处理
    /// </summary>
    /// <param name="_processAction"></param>
    /// <param name="_failDelegate"></param>
    /// <param name="_isFailContinue">是否出错了仍然继续</param>
    /// <returns>返回自身，可以继续添加步骤</returns>
    public ALMultiProcess addMultiProcess(_IALProcessAction _processAction)
    {
        return addMultiProcess(_processAction, null, false);
    }
    public ALMultiProcess addMultiProcess(_IALProcessAction _processAction, _IALProcessAction _failDelegate, boolean _isFailContinue)
    {
        if(isRunning())
        {
            ALServerLog.Error("add process action when process started!");
            return this;
        }

        synchronized (_m_lDealTaskList) {
        	final _AALProcess dealProcess = this;
        	final boolean tmpIsFailContinue = _isFailContinue;
	        //创建任务放入队列
	        _m_lDealTaskList.add(new ALProcessStepActionMonoTask(_processAction, processTag(), _m_lDealTaskList.size()
	        		, new _IALProcessAction() {
							@Override
							public void dealAction() {
								_m_scStepCounter.addDoneStepCount();
							}
						}
		            , _failDelegate
		            , new _IALProcessAction() {
						@Override
						public void dealAction() {
			        		//失败不继续则设置进程被中断
							if(!tmpIsFailContinue)
				            	_m_cController._enable = false;
							
			            	//调用监控对象的失败处理函数
							if(null != getMonitor())
								getMonitor().onProcessFailStop(dealProcess);
						}
					}));
        }

        return this;
    }

    public ALMultiProcess addMultiProcess(_ITALProcessFunc<Boolean> _processAction)
    {
        return addMultiProcess(_processAction, null, true);
    }
    public ALMultiProcess addMultiProcess(_ITALProcessFunc<Boolean> _processAction, _IALProcessAction _failDelegate, boolean _isFailContinue)
    {
        if(isRunning())
        {
            ALServerLog.Error("add process when process started!");
            return this;
        }

        synchronized (_m_lDealTaskList) {
        	final _AALProcess dealProcess = this;
        	final boolean tmpIsFailContinue = _isFailContinue;
	        //创建任务放入队列
	        _m_lDealTaskList.add(new ALProcessStepFuncMonoTask(_processAction, processTag(), _m_lDealTaskList.size()
	        		, new _IALProcessAction() {
							@Override
							public void dealAction() {
								_m_scStepCounter.addDoneStepCount();
							}
						}
	            , _failDelegate
	            , new _IALProcessAction() {
					@Override
					public void dealAction() {
		        		//失败不继续则设置进程被中断
						if(!tmpIsFailContinue)
			            	_m_cController._enable = false;
						
		            	//调用监控对象的失败处理函数
						if(null != getMonitor())
							getMonitor().onProcessFailStop(dealProcess);
					}
				}));
        }

        return this;
    }

    /// <summary>
    /// 获取出来可以在监控对象外围补充输出的信息
    /// </summary>
    @Override
    protected String _processMonitorExInfo()
    {
        return "[Multi: " + _m_scStepCounter.doneStep() + "/" + _m_scStepCounter.totalStep() + "]";
    }

    /// <summary>
    /// 进行处理
    /// </summary>
    @Override
    protected void _dealProcess(_IALProcessMonitor _monitor)
    {
        //无数据则直接完成
        if(_m_lDealTaskList.size() <= 0)
        {
            _onProcessDone();
            return;
        }

        synchronized (_m_lDealTaskList) {
	        //加入步骤
	        _m_scStepCounter.chgTotalStepCount(_m_lDealTaskList.size());
	        _m_scStepCounter.setAllDoneDelegate(this);
	        //逐个直接开始
	        for(int i = 0; i < _m_lDealTaskList.size(); i++)
	        {
	            //判断过程是否步骤类，是则可以设置监控对象
	            _m_lDealTaskList.get(i).setMonitor(_monitor);
	
	            ALSynTaskManager.getInstance().regTask(_m_lDealTaskList.get(i));
	        }
	
	        _m_lDealTaskList.clear();
        }
    }

    /// <summary>
    /// 当子处理对象完成时的处理
    /// </summary>
    @Override
    protected void _onChildDone()
    {
        _m_scStepCounter.addDoneStepCount();
    }

    /// <summary>
    /// 重置处理
    /// </summary>
    @Override
    protected void _onDiscard()
    {
        synchronized (_m_lDealTaskList) {
        	_m_lDealTaskList.clear();
        }
        _m_scStepCounter.resetAll();
    }

    /// <summary>
    /// 完成的处理，需要放回缓存池
    /// </summary>
    @Override
    protected void _onDone()
    {
    }
}
